
#pragma once

#include <ConnectionBroker/clientconnection/ClientConnection.h>
#include <ConnectionBroker/Packet.h>
#include <ConnectionBroker/ServerSettings.h>
#include <ConnectionBroker/Typedefs.h>

#include <boost/enable_shared_from_this.hpp>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>

#include <set>
#include <string>

namespace ConnectionBroker
{
   class Server : public boost::enable_shared_from_this<Server>
   {
      protected: //Typedefs
//      typedef boost::function<void(boost::shared_ptr<ConnectionBroker::Server>, ConnectionBroker::ClientConnectionPtr, const ConnectionBroker::Packet&)> serverCallback;

      protected: //Member variables
      std::set<ClientConnectionPtr> mClients;
      serverCallback mAppOnClientConnectCallback;
      serverCallback mAppOnClientDisconnectCallback;
      serverCallback mAppOnMessageCallback;
      serverCallback mOnClientConnectCallback;
      serverCallback mOnClientDisconnectCallback;
      serverCallback mOnMessageCallback;
      const ConnectionBroker::ServerSettings mSettings;
      boost::mutex mMutex;

      public: //Constructor, destructor
      Server(const ConnectionBroker::ServerSettings& settings, 
             serverCallback pDefaultCallback, 
             serverCallback pDefaultClientConnectCallback,
             serverCallback pDefaultClientDisconnectCallback
            );
      virtual ~Server();

      public: //Abstract interface
      virtual void start() = 0;

      public: //Interface
      virtual void addClient(ConnectionBroker::ClientConnectionPtr pClient);
      virtual void messageReceived(ConnectionBroker::ClientConnectionPtr pSender, const std::string& pMessage);
      virtual void messageReceived(ConnectionBroker::ClientConnectionPtr pSender, const std::string& pMessage, const uint32_t pChannel);
      virtual void messageReceived(ConnectionBroker::ClientConnectionPtr pSender, const ConnectionBroker::Packet& pPacket);
      virtual uint32_t numberOfClientsSubscribedTo(const uint32_t channelNumber);
      virtual void removeClient(ConnectionBroker::ClientConnectionPtr pClient);
      virtual void removeOnMessageCallback();
      virtual void setOnClientConnectCallback(serverCallback pCallback);
      virtual void setOnClientDisconnectCallback(serverCallback pCallback);
      virtual void setOnMessageCallback(serverCallback pCallback);
      virtual void write(ConnectionBroker::ClientConnectionPtr pRecipient, const Packet& pMessage);
      virtual void writeToAll(const Packet& pMessage);
   };
   //typedef boost::shared_ptr<Server> ServerPtr;
}

